# =================列表推导式=================
# 一个列表循环，通过表达式计算返回一个新的列表，这种可以写到一行里，即列表推导式

def fn(x):
    return x * 2

list1 = []
for i in range(10):
    list1.append(i * 2)
print(list1)


list2 = [i * 2 for i in range(10)]
print(list2)


list3 = [fn(i) for i in range(10)]
print((list3))


list4 = [str(i)+'_'+ j for i in range(4) for j in ['g','r','j','w']]
print(list4)



# ===============条件赋值=======================
animal = ''
animal1 = ''
flag = 0
if flag == 1:
    animal1 = 'mao'
else:
    animal1 = 'gou'

animal = '猫' if flag == 1 else '狗'
print(animal)
print(animal1)


# list5 = [int(range(2,9,2))]
# list6 = [int(range(5,0,-1))]
list7 = [1,2,4,8,6,7,9,4,3,7,1,0]
list7 = [0 if (i < 5) else 1 for i in list7]
print(list7)

# ================map方法===========================
# map方法 能遍历第二个参数，用第一个参数表达式处理每一个元素，
# 并用list方法将map转化为一个列表
res = list(map(fn, range(5)))
print(res)


# map方法如果有多个列表，不会多层循环，只遍历一次，每个列表对应下标进行运算
rec = list(map(lambda x,y:str(x)+'_'+y, range(5),['a','f','fd','h','e']))
print(rec)


# ===============filter方法========================
# filter方法 第一个参数的函数返回Ture， 当前元素保留，反之过滤
re = list(filter(lambda x: x % 2, range(1,101)))
re1 = list(filter(lambda x:not x % 2, range(1,101)))
print(re)
print(re1)




# ==========异常==============
# 程序在运行的时候遇到特殊情况，不能自行解决，会终止程序，并抛出异常

# excepiton 只会执行一条语句，不会多分支同时执行

# 异常的处理
# try:
#     child.met1()
#  当异常发生时执行

# except TypeError:
#     print('错误，请检测代码')

# 当异常不发生时执行
# else:
#     print('这个程序对')

# 异常发不发生都执行
# finally:
#     print('代码无错误')


# ============程序抛出异常==================
# 用raise 关键字，后面跟异常对象  raise BaseException('数列的序号要从0开始')
# i = int(input('输入1：'))
# if i == 1 :
#     raise BaseException('这首歌唱给你听')



# ============迭代器==========================
# 迭代是访问集合/列表元素的一种方式，它能记住你访问的位置，每一次访问返回下一个值，直到结尾返回结束标志
# 迭代器能按照迭代的方向进行依次迭代， （位置指针只能往前走，不能向后）
# 迭代器相关的两个基本方法
# iter()
# next()

list8 = [1,2,3,4,56,7,8,9,]
it = iter(list8)
# print(next(it))
# print(next(it))
# print(next(it))
for i in it:
    print(i)

# 自定义迭代器类
# 创建一个类，只需要实现两个方法：_iter_ ; _next_
# _iter_ 返回对象本身
# _next_ 返回下一个数据

class Myiter:
    def __init__(self):
        self.num = 0
    def __iter__(self):
        # 初始化一个属性
        return self

    def __next__(self):
        self.num += 10
        if self.num < 60:
            return self.num
        else:
            # 迭代完成，抛出终止异常
            raise StopIteration


my_iter = Myiter()
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
print(next(my_iter))
# 超出范围会抛出异常
# print(next(my_iter))

my_iter2 = Myiter()
for i in my_iter2:
    print(i)

# =============StopIteration================
# StopIteration异常用于标志迭代器结束，防止死循环
# 在next方法中，如果数据已经迭代完成，就抛出异常



# ==============yield（生成器）==========================
# 返回值并可以进入下一次迭代
# yield 关键字多用于循环函数中，迭代器的
# 如果函数中用到yield关键字，这个返回的就是生成器（迭代器）对象

def desc_num(n):
    while n >= 0:
        # yield 返回一个值，返回之后就会停下来（能记住执行的位置），
        # 直到下一次的调用（作用类似于迭代器）
        # 返回一个迭代器
        yield n
        n -= 1
        # return 是结束函数
        # return n

iter = desc_num(4)
iter1 = desc_num(6)
print(next(iter))
print(next(iter))
print(next(iter))
print(next(iter))
print(next(iter))
# 直到0，超出会抛出异常
# print(next(iter))

for i in iter1:
    print(i)



# ===========enumerate关键字和zip====================
# 用于既要列表的元素内容，又要列表元素的序号

list9=[1,3,4,6,7,8,9,10]

# for in 循环的同时需要循环变量（序号）
# for i in range(len(list9)):
#     print(list9[i-1])

# enumerate封装之后，返回第一个值是从0开始的序号，第二个值是迭代出来的内容
for index,value in enumerate(list9):
    print(index,value)

for i in enumerate(list9):
    # 一个变量返回的就是，序号和内容的元组
    print(i)

list5= ['z','c','f','t','y']

# 拆分列表的每一个元素，分别创建元组，返回一个可迭代对象
z1 = zip(list5)
for s in z1:
    print(s)

# 多个列表压缩，会以按长度最短的为准，把每一个对应下标的元素取出生成元组
z2 = zip(list5,list9,list8,list1)
for s in z2:
    print(s)

z3 = zip(range(len(list9)),list9)
for s in z3:
    print(s)


# ============= *args 和 **kwargs ==================
# 定义方法的参数时，不确定参数就用 *args 和 *kwargs 两个参数
    #  *args 是一个习惯用法，就是arguments的缩写，也可以用其它名称，前面用星号固定
            # *zxc  *dad 都可以
    # **kwargs  是keyword arguments的缩写，也是习惯写法，也可改名，前加 ** 固定
    # 两个星号是参数代表任意个数的关键字参数（命名参数），调用的参数是关键字的参数
            # 如：fn =（name=‘张三’，age=22）

    # 如果一个方法两个参数都有，一般 *args 在前 ， **kwargs 在后

def fn(*args,**kwargs):
    for arg in args:
        print(arg)
    for kwarg in kwargs.items():
        print(kwarg)

fn(15,454,'hfh','jbju',fssgg=544,sfdsf=454)